﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Shapes;
using System.Diagnostics;
using ASPItalia.ModelVirtualCasting.WPF.ViewModels;

namespace ASPItalia.ModelVirtualCasting.WPF.Views
{
    /// <summary>
    /// Interaction logic for ImageEditorView.xaml
    /// </summary>
    public partial class ImageEditorView : Window
    {
        public ImageEditorView()
        {
            InitializeComponent();
        }

        private void CloseButton_Click(object sender, RoutedEventArgs e)
        {
            this.Close();
        }

        protected ImageEditorViewModel ViewModel
        {
            get { return (ImageEditorViewModel)this.DataContext; }
        }

        private void imageContainer_ManipulationStarting(object sender, ManipulationStartingEventArgs e)
        {
            e.ManipulationContainer = this.imageContainer;
            e.Mode = ManipulationModes.All;
        }

        private Vector scale = new Vector(1, 1);

        private void imageContainer_ManipulationDelta(object sender, ManipulationDeltaEventArgs e)
        {
            var element = e.Source as FrameworkElement;
            if (element != null)
            {
                MatrixTransform matrixTransform = element.RenderTransform as MatrixTransform;
                if (matrixTransform == null || matrixTransform.Matrix.IsIdentity)
                    element.RenderTransform = matrixTransform = new MatrixTransform();

                Matrix matrix = matrixTransform.Matrix;

                ManipulationDelta deltaManipulation = e.DeltaManipulation;
                // Find the old center; arguaby this could be cached 
                Point center = new Point(element.ActualWidth / 2, element.ActualHeight / 2);
                // Change previous transform basing on new size
                center = matrix.Transform(center);
                // Zoom 
                matrix.ScaleAt(deltaManipulation.Scale.X, deltaManipulation.Scale.Y, center.X, center.Y);
                scale = deltaManipulation.Scale;

                // Rotation 
                matrix.RotateAt(e.DeltaManipulation.Rotation, center.X, center.Y);
                //Translation (pan) 
                matrix.Translate(e.DeltaManipulation.Translation.X, e.DeltaManipulation.Translation.Y);

                matrixTransform.Matrix = matrix;

                e.Handled = true;
            }
        }

        private Point? startPoint;

        private void imageContainer_TouchDown(object sender, TouchEventArgs e)
        {
            if (!(e.Source is Image))
            {
                startPoint = e.GetTouchPoint(this.image).Position;
            }
        }

        private void imageContainer_TouchUp(object sender, TouchEventArgs e)
        {
            if (startPoint.HasValue)
            {
                Point endPoint = e.GetTouchPoint(this.image).Position;

                BitmapSource source = this.ViewModel.ImageSource;
                Int32Rect previsousRect = new Int32Rect(0, 0, source.PixelWidth, source.PixelHeight);
                if (source is CroppedBitmap)
                {
                    CroppedBitmap oldcb = ((CroppedBitmap)source);
                    source = oldcb.Source;
                    previsousRect = oldcb.SourceRect;
                }

                // TODO: compute also scale and transform
                startPoint = new Point(Math.Max(0, Math.Min(startPoint.Value.X, source.Width)), Math.Max(0, Math.Min(startPoint.Value.Y, source.Height)));
                endPoint = new Point(Math.Max(0, Math.Min(endPoint.X, source.Width)), Math.Max(0, Math.Min(endPoint.Y, source.Height)));

                // 1;0;0;1;24;4
                // ScaleX;RotateX;RotateY;ScaleY;OffsetX;OffsetY
                Matrix matrix = image.RenderTransform.Value;

                bool horDir = (Math.Abs(startPoint.Value.X - endPoint.X) > Math.Abs(startPoint.Value.Y - endPoint.Y));
                int x = (int)((startPoint.Value.X) / 96 * source.DpiX);
                int y = (int)((startPoint.Value.Y) / 96 * source.DpiY);

                bool upToDown = (horDir) ? (previsousRect.Height / 2 > y) : (previsousRect.Width / 2 > x);

                Debug.WriteLine(String.Format("{0} {1}", x, y));

                CroppedBitmap cb = new CroppedBitmap();
                cb.BeginInit();
                cb.Source = source;
                if (horDir)
                {
                    if (upToDown)
                        cb.SourceRect = new Int32Rect(previsousRect.X, y + previsousRect.Y, previsousRect.Width, previsousRect.Height - y);
                    else
                        cb.SourceRect = new Int32Rect(previsousRect.X, previsousRect.Y, previsousRect.Width, previsousRect.Height - (previsousRect.Height - y));
                }
                else
                {
                    if (upToDown)
                        cb.SourceRect = new Int32Rect(previsousRect.X + x, y, previsousRect.Width - x, previsousRect.Height);
                    else
                        cb.SourceRect = new Int32Rect(previsousRect.X, previsousRect.Y, previsousRect.Width - (previsousRect.Width - x), previsousRect.Height);
                }
                cb.EndInit();

                this.ViewModel.ImageSource = cb;
            }
            startPoint = null;
        }
    }
}
